/**
* \file Jeu.c
* \brief Comprend les fonctions et les procédures utiles pour l'exécution du jeu
*/

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include "Parametres.h"
#include "Combinaison.h"
#include "Jeu.h"


#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>



/**
* \fn void initJeuTexte (Jeu* jeu, Parametres param, int nbjoueurs)
* \brief La procédure initJeuTexte initialise tous les champs de la structure Jeu.
* \details Initialisation du nombre d'essais à 10, du score à 500,
*          création des différents tableaux et initialisation,
*          génération de la combinaison secrète (mode 1 et 2 joueurs) pour le mode texte.
*/

void initJeuTexte (Jeu* jeu, Parametres param, int nbjoueurs)
{
    jeu-> nbEssais = 10;
    jeu-> score = 500;
    jeu-> tabCombinaisonsTestees = (Combinaison*) malloc(10*sizeof(Combinaison));
    jeu-> tabNbPionsBienPlaces = (int*) malloc(10*sizeof(int));
    jeu-> tabNbPionsBonneCouleur = (int*) malloc(10*sizeof(int));

    assert(nbjoueurs==1 || nbjoueurs==2);
    assert(param.taille>0);

    if(nbjoueurs == 2)
    {
        initCombinaison(&jeu-> combinaisonSecrete, param);
        saisieCombinaisonSecreteTexte(&jeu-> combinaisonSecrete, param);
    }

    else
    {
        generationAleatoireCombinaisonSecreteTexte (&jeu-> combinaisonSecrete, param);
    }

    /*Initialisations*/
    int k=0;
    for(k= 0; k< 10; k++)
    {
        initCombinaison (&jeu->tabCombinaisonsTestees[k], param);
        jeu->tabNbPionsBienPlaces[k] = 0;
        jeu->tabNbPionsBonneCouleur[k] = 0;
    }
}



/**
* \fn void initJeuSDL (Jeu* jeu, Parametres param, int nbjoueurs, SDL_Surface* screen)
* \brief La procédure initJeuSDL initialise tous les champs de la structure Jeu.
* \details Initialisation du nombre d'essais à 10, du score à 500,
*          création des différents tableaux et initialisation,
*          génération de la combinaison secrète en SDL.
*/

void initJeuSDL (Jeu* jeu, Parametres param, int nbjoueurs, SDL_Surface* screen, int* applicationOuverte)
{
    jeu-> nbEssais = 10;
    jeu-> score = 500;
    jeu-> tabCombinaisonsTestees = (Combinaison*) malloc(10*sizeof(Combinaison));
    jeu-> tabNbPionsBienPlaces = (int*) malloc(10*sizeof(int));
    jeu-> tabNbPionsBonneCouleur = (int*) malloc(10*sizeof(int));

    if(nbjoueurs == 1)
    {
        generationAleatoireCombinaisonSecreteSDL (&jeu-> combinaisonSecrete, param);
    }

    else if(nbjoueurs == 2)
    {
        SDL_Surface *plateauDeJeu = NULL;

        /* Chargement des images selon le niveau choisi */
        if (param.taille == 3)
        {
            plateauDeJeu = chargerImage2 ("data/saisie2Joueurs3.bmp");
        }

        else if (param.taille == 4)
        {
            plateauDeJeu = chargerImage2 ("data/saisie2Joueurs4.bmp");
        }

        else
        {
            plateauDeJeu = chargerImage2 ("data/saisie2Joueurs5.bmp");
        }

        appliquerSurface2(plateauDeJeu, screen, 0, 0);
        jeu->combinaisonSecrete = saisieCombinaisonSDL(param, screen, applicationOuverte, 201, 301);
        SDL_FreeSurface(plateauDeJeu);
    }

    /* Initialisations */
    int k=0;
    for(k= 0; k< 10; k++)
    {
        initCombinaison (&jeu->tabCombinaisonsTestees[k], param);
        jeu->tabNbPionsBienPlaces[k] = 0;
        jeu->tabNbPionsBonneCouleur[k] = 0;
    }
}



/**
* \fn void remplirTableaux (Jeu* jeu, Parametres param, Combinaison* comb, int numEssai)
* \brief La procédure remplirTableaux remplit le tableau de combinaisons testées
*        ainsi que les tableaux d'indications de jeu (pionsBienPlaces, pionsBonneCouleur).
*/

void remplirTableaux (Jeu* jeu, Parametres param, Combinaison* comb, int numEssai)
{
    int i;
    assert (numEssai >= 0 && numEssai <= 9);  /* Le nombre maximal d'essais est 10 */

    jeu->tabNbPionsBienPlaces[numEssai] = pionsBienPlaces(comb, &jeu->combinaisonSecrete);
    jeu->tabNbPionsBonneCouleur[numEssai] = pionsBonneCouleur(comb, &jeu->combinaisonSecrete, param);

    for(i=0; i<comb->taille; i++)
    {
        jeu->tabCombinaisonsTestees[numEssai].tab[i] = comb->tab[i];
    }

}


/**
* \fn void libereJeu (Jeu* jeu)
* \brief La procédure libereJeu libère les différents tableaux et variables utilisés.
* \details Cette procédure permet de libérer proprement le jeu.
*/

void libereJeu (Jeu* jeu)
{
    int i=0;

    jeu-> nbEssais = 0;
    jeu-> score = 0;

    for (i=0; i<10; i++)
    {
        libereCombinaison(&jeu-> tabCombinaisonsTestees[i]);
    }
    free (jeu-> tabCombinaisonsTestees);

    free (jeu-> tabNbPionsBienPlaces);
    free (jeu-> tabNbPionsBonneCouleur);

    libereCombinaison(&jeu-> combinaisonSecrete);
}


/**
* \fn void calculScore(Jeu* jeu, Parametres param, int i)
* \brief La procédure calculScore permet de calculer le score à chaque essai.
* \details Le score initial est de 500. A chaque essai, si la combinaison secrète n'est pas trouvée,
*          le score diminue de la manière suivante :
*             - 0 pour les pions bien placés
*             - -5 pour les pions mal placés mais dont la couleur fait partie de la combinaison secrète
*             - -10 pour les pions dont la couleur ne fait pas partie de la combinaison secrète
*/

void calculScore(Jeu* jeu, Parametres param, int i)
{
    jeu->score = jeu->score + (-5)*jeu->tabNbPionsBonneCouleur[i] + (-10)*(param.taille - jeu->tabNbPionsBienPlaces[i] - jeu->tabNbPionsBonneCouleur[i]) ;
}


/**
* \fn SDL_Surface *chargerImage2(const char* filename)
* \brief La procédure chargerImage2 permet de charger une image.
*/

SDL_Surface *chargerImage2(const char* filename)
{
	/*Surface tampon qui nous servira pour charger l'image*/
	SDL_Surface* imageChargee = NULL;

    /*L'image optimisée qu'on va utiliser*/
	SDL_Surface* imageOptimisee = NULL;

	/*Chargement de l'image*/
	imageChargee = SDL_LoadBMP( filename );

	/*Si le chargement se passe bien*/
	if( imageChargee != NULL ) {
		/*Création de l'image optimisée*/
		imageOptimisee = SDL_DisplayFormat( imageChargee );

		/*Libération de l'ancienne image*/
		SDL_FreeSurface( imageChargee );
	}

	/*On retourne l'image optimisée*/
	return imageOptimisee;
}



/**
* \fn void appliquerSurface2(SDL_Surface* source, SDL_Surface* destination, int x, int y)
* \brief La procédure appliquerSurface2 permet d'appliquer une image sur une surface SDL.
*/

void appliquerSurface2(SDL_Surface* source, SDL_Surface* destination, int x, int y)
{
	/*Rectangle temporaire*/
	SDL_Rect offset;

	offset.x = x;
	offset.y = y;

	/* Blit de la surface*/
	SDL_BlitSurface(source, NULL, destination, &offset);
}
